using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
using YooAsset;
using Object = UnityEngine.Object;

namespace ZFramework.Runtime
{
    public class YooResourceMgr : FrameworkManagerBase, IResourceMgr
    {
        private string _packageName = "DefaultPackage";

        private ResourcePackage _package;

        private EPlayMode _playMode = EPlayMode.EditorSimulateMode;

        protected override void Awake()
        {
            base.Awake();
            
        }

        void Start()
        {
            YooAssets.Initialize();
        }

        public void SetPlayMode(EPlayMode playMode)
        {
            _playMode = playMode;
        }

        public void InitResource(InitResourcesCompleteCallback initResourcesCompleteCallback)
        {
            _InitResource(initResourcesCompleteCallback).Forget();
        }

        private async UniTaskVoid _InitResource(InitResourcesCompleteCallback initResourcesCompleteCallback)
        {
            var package = YooAssets.CreatePackage(_packageName);
            YooAssets.SetDefaultPackage(package);

            InitializationOperation initializationOperation = null;
            if (_playMode == EPlayMode.EditorSimulateMode)
            {
                var createParameters = new EditorSimulateModeParameters();
                createParameters.SimulateManifestFilePath =
                    EditorSimulateModeHelper.SimulateBuild(EDefaultBuildPipeline.BuiltinBuildPipeline.ToString(),
                        _packageName);
                initializationOperation = package.InitializeAsync(createParameters);
            }else if (_playMode == EPlayMode.OfflinePlayMode)
            {
                var createParameters = new OfflinePlayModeParameters();
                initializationOperation = package.InitializeAsync(createParameters);
            }else if (_playMode == EPlayMode.HostPlayMode)
            {
                Log.Error("暂不支持热更模式");
                return;
            }

            await initializationOperation;
            if (initializationOperation.Status != EOperationStatus.Succeed)
            {
                Log.Error("初始化yooAsset失败");
                return;
            }

            _package = package;
            initResourcesCompleteCallback?.Invoke();
        }

        public override void Shutdown()
        {
            YooAssets.Destroy();
        }

        public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
        {
            
        }

        public void LoadAssetAsync<T>(string assetPath, LoadAssetCallbacks loadAssetCallbacks, object userData = null)
            where T : Object
        {
            _LoadAssetAsync<T>(assetPath, loadAssetCallbacks, userData).Forget();
        }
        
        public void UnloadAsset(string assetPath)
        {
            _package.TryUnloadUnusedAsset(assetPath);
        }

        public void LoadSceneAsync(string assetPath, LoadSceneCallbacks loadSceneCallbacks, object userData = null)
        {
            
        }

        public void UnloadScene(string assetPath, UnloadSceneCallbacks unloadAssetCallbacks, object userData = null)
        {
        }

        public void LoadBinary(string assetPath, LoadBinaryCallbacks loadBinaryCallbacks, object userData = null)
        {
            _LoadBinary(assetPath, loadBinaryCallbacks, userData);
        }
        
        public void UnloadBinary(string assetPath)
        {
            
        }
        
        async UniTaskVoid _LoadAssetAsync<T>(string assetPath, LoadAssetCallbacks loadAssetCallbacks, object userData = null)where T : Object
        {
            var beginTime = Time.time;
            var operation = _package.LoadAssetAsync<T>(assetPath);
            await operation.ToUniTask();
            if (operation.Status == EOperationStatus.Succeed)
            {
                var asset = operation.AssetObject as T;
                var duration = Time.time - beginTime;
                loadAssetCallbacks.LoadAssetSuccessCallback?.Invoke(assetPath, asset, duration, userData);
            }
            else
            {
                loadAssetCallbacks.LoadAssetFailureCallback?.Invoke(assetPath, operation.LastError, userData);
            }
        }

        async UniTaskVoid _LoadScene(string assetPath, LoadSceneCallbacks loadSceneCallbacks, object userData = null)
        {
            var beginTime = Time.time;
            var operation = _package.LoadSceneAsync(assetPath, LoadSceneMode.Single, true);
            await operation.ToUniTask();
            if (operation.Status == EOperationStatus.Succeed)
            {
                
            }
            else
            {
                
            }
        }

        async UniTaskVoid _LoadBinary(string assetPath, LoadBinaryCallbacks loadBinaryCallbacks, object userData = null)
        {
            var beginTime = Time.time;
            var operation = _package.LoadRawFileAsync(assetPath);
            await operation.ToUniTask();
            if (operation.Status == EOperationStatus.Succeed)
            {
                var fileData = operation.GetRawFileData();
                var duration = Time.time - beginTime;
                loadBinaryCallbacks.LoadBinarySuccessCallback?.Invoke(assetPath, fileData, duration, userData);
            }
            else
            {
                loadBinaryCallbacks.LoadBinaryFailureCallback?.Invoke(assetPath, operation.LastError, userData);
            }
        }
        
        
    }
}
